package top.zywork.strategy.order;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.zywork.constant.CommonConstant;
import top.zywork.dos.SchoolOrderDO;
import top.zywork.dto.OrderPayDTO;
import top.zywork.dto.RefundOrderDTO;
import top.zywork.enums.*;
import top.zywork.exception.GlobalException;
import top.zywork.security.SecurityUtils;
import top.zywork.service.SchoolOrderService;
import top.zywork.weixin.PayResult;
import top.zywork.weixin.RefundResult;
import top.zywork.weixin.WXPayConfig;
import top.zywork.weixin.WeixinXcxConfig;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 快递代拿
 * @author Animo
 * @Date 2020/10/21
 * @Blog http://www.ljyanimo.com
 */
@Service
@Slf4j
public class DeliveryOrderService implements OrderService {

    @Autowired
    private BaseOrder baseOrder;


    /**
     * 当前快递代拿回调地址
     */
    private static String payNotifyUrl = CommonConstant.DOMAIN + "/wx-pay/goods-order/wx-pay-notify/" + PayOrderEnum.KDDN.getName();

    /**
     * 快递代拿取消订单回调地址
     */
    private static String refundNotifyUrl = CommonConstant.DOMAIN + "/wx-pay/goods-order/wx-refund-notify/" + RefundOrderEnum.KDDN_REFUND.getName();

    @Autowired
    private SchoolOrderService schoolOrderService;

    @Override
    public OrderPayDTO orderValidation(String orderId) {
        String[] orderIdA = orderId.split(",");
        List<SchoolOrderDO> schoolOrderDOList = schoolOrderService.list(new QueryWrapper<SchoolOrderDO>()
                .in("id", orderIdA)
                .eq("user_id", SecurityUtils.getJwtUser().getUserId())
                .eq("pay_status", PayStatusEnum.TO_BE_PAID.getCode())
                .eq("is_active", CommonConstant.IS_ACTIVE_FALSE));

        if(schoolOrderDOList.size() != orderIdA.length){
            throw new GlobalException("支付订单号有误");
        }
        // 检查完订单号之后获取支付的金额
        BigDecimal totalPay = schoolOrderDOList.stream().map(SchoolOrderDO::getPayAmount).reduce(BigDecimal.ZERO,BigDecimal::add);
        return new OrderPayDTO(totalPay,payNotifyUrl);
    }

    @Override
    public RefundOrderDTO refundValidation(String orderId) {
        // 订单状态、下单人id、支付状态（已支付）、激活状态、订单状态（待接单）
        SchoolOrderDO one = schoolOrderService.getOne(new QueryWrapper<SchoolOrderDO>()
                .eq("id", orderId)
                .eq("user_id", SecurityUtils.getJwtUser().getUserId())
                .eq("pay_status", PayStatusEnum.HAVE_TO_PAY.getCode())
                .eq("is_active", CommonConstant.IS_ACTIVE_TRUE)
                .eq("status", SchoolOrderStatusEnum.WAITING_LIST.getCode()));
        if(one == null){
            throw new GlobalException("订单退款异常~");
        }
        // 获取微信支付信息
        RefundOrderDTO refundOrderDTO = new RefundOrderDTO();
        // 设置交易编号
        refundOrderDTO.setTransactionNo(one.getTransactionNo());
        // 退款订单号
        refundOrderDTO.setOutRefundNo(one.getId());
        // 支付金额
        refundOrderDTO.setTotalFee(one.getPayAmount().multiply(new BigDecimal(100)).intValue());
        // 退款金额
        refundOrderDTO.setRefundFee(one.getPayAmount().multiply(new BigDecimal(100)).intValue());
        // 退款描述
        refundOrderDTO.setRefundDesc(RefundOrderEnum.KDDN_REFUND.getDes() + one.getId());
        // 退款回调
        refundOrderDTO.setRefundNotifyUrl(refundNotifyUrl);
        return refundOrderDTO;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void wxPaySuccessNotify(PayResult payResult) {

        log.info("代拿下单支付成功回调：{}" ,payResult.toString());
        /**
         * 修改订单状态（待接单） 为激活和已支付
         */
        JSONObject attachJsonObj = JSONObject.parseObject(payResult.getAttach());
        Long userId = attachJsonObj.getLong("userId");
        String orderIdAndNos = attachJsonObj.getString("orderIdAndNos");
        String[] orderIdAndNoAry = orderIdAndNos.split(",");

        List<SchoolOrderDO> orderResult = schoolOrderService.list(new QueryWrapper<SchoolOrderDO>().in("id", orderIdAndNoAry));
        BigDecimal amount = new BigDecimal(payResult.getTotalFee() / 100.0).setScale(2, BigDecimal.ROUND_HALF_UP);
        orderResult = orderResult.stream().map(e -> {
            // 设置待接单状态
            e.setStatus(SchoolOrderStatusEnum.WAITING_LIST.getCode());
            // 设置激活状态
            e.setIsActive(CommonConstant.IS_ACTIVE_TRUE);
            // 设置已支付状态
            e.setPayStatus(PayStatusEnum.HAVE_TO_PAY.getCode());
            // 下单时间
            e.setPlaceOrderTime(new Date());
            // 交易编号
            e.setTransactionNo(payResult.getTransactionId());
            return e;
        }).collect(Collectors.toList());
        // 批量更新订单表
        schoolOrderService.updateBatchById(orderResult);
        /**
         * 只有在成功付款后才会保存用户账目和平台账目
         */
        // 保存用户账目表
        baseOrder.saveAccountDetail(userId, payResult.getTransactionId(), IncomeOutgoingTypeEnum.OUTGOING.getValue(), amount.negate(),AccountTypeEnum.DELIVERY_FOR.getValue(), orderIdAndNos);

        // 平台账目表 快递代拿 收入
        baseOrder.savePlatformAccountDetail(userId, payResult.getTransactionId(), AccountTypeEnum.DELIVERY_FOR.getValue(),amount ,orderIdAndNos);

    }

    @Override
    public void wxPayFailNotify(PayResult payResult) {
        System.out.println(payResult);
    }

    @Override
    public void wxRefundSuccessNotify(RefundResult refundResult) {
        // 统一退款回调
        System.out.println(refundResult);

        // TODO 退款成功的话 需要把优惠券也一并退回

        // 系统订单号
        String outTradeNo = refundResult.getOutRefundNo();

        // 微信订单号 流水
        String transactionId = refundResult.getTransactionId();

        SchoolOrderDO order = schoolOrderService.getOne(new QueryWrapper<SchoolOrderDO>().eq("id", outTradeNo));

        // 更改激活状态
        order.setIsActive(CommonConstant.IS_ACTIVE_FALSE);

        schoolOrderService.updateById(order);
    }

    @Override
    public void wxRefundFailNotify(RefundResult refundResult) {

    }
}
